"""DNS管理器."""

from typing import List, Optional

from sqlalchemy import select, and_
from sqlalchemy.ext.asyncio import AsyncSession

from netsphere.models.dns import DNSRecord, DNSView, DNSZone
from netsphere.models.ipam import IPAddress


class DNSManager:
    """DNS管理器，负责DNS区域和记录管理."""
    
    def __init__(self, session: AsyncSession):
        """初始化DNS管理器.
        
        Args:
            session: 数据库会话
        """
        self.session = session
    
    async def create_view(
        self,
        name: str,
        description: str = None,
        match_clients: str = None,
    ) -> DNSView:
        """创建DNS视图.
        
        Args:
            name: 视图名称
            description: 描述信息
            match_clients: 客户端匹配规则
            
        Returns:
            DNSView实例
        """
        view = DNSView(
            name=name,
            description=description,
            match_clients=match_clients,
        )
        self.session.add(view)
        await self.session.commit()
        return view
    
    async def create_zone(
        self,
        name: str,
        zone_type: str = "master",
        primary_ns: str = None,
        admin_email: str = None,
        view_id: int = None,
        **kwargs
    ) -> DNSZone:
        """创建DNS区域.
        
        Args:
            name: 区域名称
            zone_type: 区域类型（master, slave, forward）
            primary_ns: 主DNS服务器
            admin_email: 管理员邮箱
            view_id: 视图ID
            **kwargs: 其他SOA记录参数
            
        Returns:
            DNSZone实例
        """
        zone = DNSZone(
            name=name,
            zone_type=zone_type,
            primary_ns=primary_ns or "ns1.example.com",
            admin_email=admin_email or "admin.example.com",
            view_id=view_id,
            **kwargs
        )
        self.session.add(zone)
        await self.session.commit()
        return zone
    
    async def create_record(
        self,
        zone_id: int,
        name: str,
        record_type: str,
        value: str,
        ttl: int = 3600,
        priority: int = None,
        ip_address_id: int = None,
    ) -> DNSRecord:
        """创建DNS记录.
        
        Args:
            zone_id: 区域ID
            name: 记录名称
            record_type: 记录类型（A, AAAA, CNAME, MX, TXT等）
            value: 记录值
            ttl: TTL值
            priority: 优先级（MX记录使用）
            ip_address_id: 关联的IP地址ID
            
        Returns:
            DNSRecord实例
        """
        record = DNSRecord(
            zone_id=zone_id,
            name=name,
            record_type=record_type,
            value=value,
            ttl=ttl,
            priority=priority,
            ip_address_id=ip_address_id,
        )
        self.session.add(record)
        
        # 更新区域序列号
        zone = await self.session.get(DNSZone, zone_id)
        if zone:
            zone.bump_serial()
            self.session.add(zone)
        
        await self.session.commit()
        return record
    
    async def get_zone_by_name(
        self, 
        name: str, 
        view_id: int = None
    ) -> Optional[DNSZone]:
        """根据名称获取区域.
        
        Args:
            name: 区域名称
            view_id: 视图ID（可选）
            
        Returns:
            DNSZone实例或None
        """
        query = select(DNSZone).where(DNSZone.name == name)
        if view_id is not None:
            query = query.where(DNSZone.view_id == view_id)
        
        result = await self.session.execute(query)
        return result.scalar_one_or_none()
    
    async def list_zones(
        self,
        view_id: int = None,
        is_active: bool = None,
    ) -> List[DNSZone]:
        """列出区域.
        
        Args:
            view_id: 视图ID（可选）
            is_active: 过滤活跃状态
            
        Returns:
            区域列表
        """
        query = select(DNSZone)
        if view_id is not None:
            query = query.where(DNSZone.view_id == view_id)
        if is_active is not None:
            query = query.where(DNSZone.is_active == is_active)
        
        result = await self.session.execute(query)
        return list(result.scalars().all())
    
    async def list_records(
        self,
        zone_id: int,
        record_type: str = None,
        name: str = None,
        is_active: bool = None,
    ) -> List[DNSRecord]:
        """列出DNS记录.
        
        Args:
            zone_id: 区域ID
            record_type: 记录类型（可选）
            name: 记录名称（可选）
            is_active: 过滤活跃状态
            
        Returns:
            DNS记录列表
        """
        query = select(DNSRecord).where(DNSRecord.zone_id == zone_id)
        
        if record_type is not None:
            query = query.where(DNSRecord.record_type == record_type)
        if name is not None:
            query = query.where(DNSRecord.name == name)
        if is_active is not None:
            query = query.where(DNSRecord.is_active == is_active)
        
        result = await self.session.execute(query)
        return list(result.scalars().all())
    
    async def search_records(
        self,
        name: str,
        record_type: str = None,
    ) -> List[DNSRecord]:
        """搜索DNS记录.
        
        Args:
            name: 记录名称或通配符
            record_type: 记录类型（可选）
            
        Returns:
            DNS记录列表
        """
        query = select(DNSRecord).where(
            DNSRecord.name.like(f"%{name}%")
        )
        
        if record_type is not None:
            query = query.where(DNSRecord.record_type == record_type)
        
        result = await self.session.execute(query)
        return list(result.scalars().all())
    
    async def delete_record(self, record_id: int) -> bool:
        """删除DNS记录.
        
        Args:
            record_id: 记录ID
            
        Returns:
            是否成功删除
        """
        record = await self.session.get(DNSRecord, record_id)
        if not record:
            return False
        
        zone_id = record.zone_id
        await self.session.delete(record)
        
        # 更新区域序列号
        zone = await self.session.get(DNSZone, zone_id)
        if zone:
            zone.bump_serial()
            self.session.add(zone)
        
        await self.session.commit()
        return True